/**************************************************************************
Copyright (C) 2008-2010 United States Government. All rights reserved. 

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
****************************************************************************/
package rage

import grails.test.*;
import org.codehaus.groovy.grails.commons.ConfigurationHolder;

import rage.filters.Filter
import rage.filters.StringFilter

class GoogleEarthDashboardControllerTests extends ControllerUnitTestCase {
	
	String rageServerURL = "localhost:8080/RAGE";

	protected void setUp() {
		super.setUp();
	}

	protected void tearDown() {
		super.tearDown();
	}

	void testKml() {
		def feedName = "feed";
		def feedDescription = "This Feed is the best!";
		def color1 = "ff0000";
		def color2 = "ffff00";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(2..2) {String arg1, String arg2, String arg3 -> 
			return [responsecode: 200, content: "feed xml"]
		};
		controller.getService = getServiceMock.createMock();

		//Set up mock for feedParserService
		def feedParserServiceMock = mockFor(FeedParserService);
		feedParserServiceMock.demand.parseFeed(2..2) {String arg1, List<Filter> arg2 -> 
			Feed feed = new Feed();
			feed.title = feedName;
			feed.description = feedDescription;
			return feed
		};
		controller.feedParserService = feedParserServiceMock.createMock();

		controller.params.feedUrl1 = "http://localhost:8080/feed1";
		controller.params.feedColor1 = "#" + color1;
		controller.params.feedUrl2 = "http://localhost:8080/feed2";
		controller.params.feedColor2 = "#" + color2;
		controller.params.titleOperator1 = "EQUALS";
		controller.params.titleFilter1 = "hello";

		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feeds'", returnMap.feeds);
		assertEquals(2, returnMap.feeds.size());
		assertFeed(returnMap.feeds.get(0), controller.params.feedUrl1, feedName, feedDescription);
		assertFeed(returnMap.feeds.get(1), controller.params.feedUrl2, feedName, feedDescription);

		assertNotNull("Controller map does not contain expected model object: 'feedColors'", returnMap.feedColors);
		assertEquals(2, returnMap.feedColors.size());
		assertEquals(color1, returnMap.feedColors.get(0));
		assertEquals(color2, returnMap.feedColors.get(1));
		
		assertNotNull("Controller map does not contain expected model object: 'feedFilters'", returnMap.feedFilters);
		assertEquals("feedFilters model object does not contain expected size", 2, returnMap.feedFilters.size());
		assertEquals("filters list(0) contains unexpected size", 0, returnMap.feedFilters.get(0).size());
		assertEquals("filters list(1) contains unexpected size", 0, returnMap.feedFilters.get(1).size());
	}

	void testKml_withTitleFilter() {
		def feedName = "feed";
		def feedDescription = "This Feed is the best!";
		def color1 = "ff0000";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(1..1) {String arg1, String arg2, String arg3 ->
			return [responsecode: 200, content: "feed xml"]
		};
		controller.getService = getServiceMock.createMock();

		//Set up mock for feedParserService
		def feedParserServiceMock = mockFor(FeedParserService);
		feedParserServiceMock.demand.parseFeed(1..1) {String arg1, List<Filter> arg2 ->
			Feed feed = new Feed();
			feed.title = feedName;
			feed.description = feedDescription;
			return feed
		};
		controller.feedParserService = feedParserServiceMock.createMock();

		controller.params.feedUrl1 = "http://localhost:8080/feed1";
		controller.params.feedColor1 = "#" + color1;
		controller.params.titleFilterCheckbox1 = "on";
		controller.params.titleOperator1 = "EQUALS";
		controller.params.titleFilter1 = "hello";

		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feedFilters'", returnMap.feedFilters);
		assertEquals("feedFilters model object does not contain expected size", 1, returnMap.feedFilters.size());
		
		List<String> filters = returnMap.feedFilters.get(0);
		assertEquals(1, filters.size());
		assertEquals("Unexpeced filter value",
			"title=EQUALS_hello", filters.get(0))
	}
	
	void testKml_withContentFilter() {
		def feedName = "feed";
		def feedDescription = "This Feed is the best!";
		def color1 = "ff0000";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(1..1) {String arg1, String arg2, String arg3 ->
			return [responsecode: 200, content: "feed xml"]
		};
		controller.getService = getServiceMock.createMock();

		//Set up mock for feedParserService
		def feedParserServiceMock = mockFor(FeedParserService);
		feedParserServiceMock.demand.parseFeed(1..1) {String arg1, List<Filter> arg2 ->
			Feed feed = new Feed();
			feed.title = feedName;
			feed.description = feedDescription;
			return feed
		};
		controller.feedParserService = feedParserServiceMock.createMock();

		controller.params.feedUrl1 = "http://localhost:8080/feed1";
		controller.params.feedColor1 = "#" + color1;
		controller.params.contentFilterCheckbox1 = "on";
		controller.params.contentOperator1 = "EQUALS";
		controller.params.contentFilter1 = "hello";

		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feedFilters'", returnMap.feedFilters);
		assertEquals("feedFilters model object does not contain expected size", 1, returnMap.feedFilters.size());
		
		List<Filter> filters = returnMap.feedFilters.get(0);
		assertEquals(1, filters.size());
		assertEquals("Unexpeced filter value",
			"content=EQUALS_hello", filters.get(0))
	}
	
	void testKml_withNumericalFilter() {
		def feedName = "feed";
		def feedDescription = "This Feed is the best!";
		def color1 = "ff0000";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(1..1) {String arg1, String arg2, String arg3 ->
			return [responsecode: 200, content: "feed xml"]
		};
		controller.getService = getServiceMock.createMock();

		//Set up mock for feedParserService
		def feedParserServiceMock = mockFor(FeedParserService);
		feedParserServiceMock.demand.parseFeed(1..1) {String arg1, List<Filter> arg2 ->
			Feed feed = new Feed();
			feed.title = feedName;
			feed.description = feedDescription;
			return feed
		};
		controller.feedParserService = feedParserServiceMock.createMock();

		controller.params.feedUrl1 = "http://localhost:8080/feed1";
		controller.params.feedColor1 = "#" + color1;
		controller.params.numericalFilterCheckbox1 = "on";
		controller.params.numericalFilterVariable1 = "M";
		controller.params.numericalOperator1 = "GREATERTHAN";
		controller.params.numericalFilterOperand1 = "3.0";
		controller.params.numericalField1 = "TITLE";
		
		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feedFilters'", returnMap.feedFilters);
		assertEquals("feedFilters model object does not contain expected size", 1, returnMap.feedFilters.size());
		
		List<Filter> filters = returnMap.feedFilters.get(0);
		assertEquals(1, filters.size());
		assertEquals("Unexpeced filter value",
			"numerical=TITLE_M_GREATERTHAN_3.0", filters.get(0))
	}
	
	void testKml_withBoundingBoxFilter() {
		def feedName = "feed";
		def feedDescription = "This Feed is the best!";
		def color1 = "ff0000";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(1..1) {String arg1, String arg2, String arg3 ->
			return [responsecode: 200, content: "feed xml"]
		};
		controller.getService = getServiceMock.createMock();

		//Set up mock for feedParserService
		def feedParserServiceMock = mockFor(FeedParserService);
		feedParserServiceMock.demand.parseFeed(1..1) {String arg1, List<Filter> arg2 ->
			Feed feed = new Feed();
			feed.title = feedName;
			feed.description = feedDescription;
			return feed
		};
		controller.feedParserService = feedParserServiceMock.createMock();

		controller.params.feedUrl1 = "http://localhost:8080/feed1";
		controller.params.feedColor1 = "#" + color1;
		controller.params.boundingBoxFilterCheckbox1 = "checked";
		controller.params.upperLeftLat1 = "-3.0";
		controller.params.upperLeftLon1 = "-2.0";
		controller.params.lowerRightLat1 = "-5.0";
		controller.params.lowerRightLon1 = "0.0";

		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feedFilters'", returnMap.feedFilters);
		assertEquals("feedFilters model object does not contain expected size", 1, returnMap.feedFilters.size());
		
		List<Filter> filters = returnMap.feedFilters.get(0);
		assertEquals(1, filters.size());
		assertEquals("Unexpeced filter value",
			"bbgeo=-3.0,-2.0,-5.0,0.0", filters.get(0))
	}
	
	void testKml_get_404() {

		def feedUrl = "http://localhost:8080/feed1";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(2..2) {String arg1, String arg2, String arg3 -> 
			return [responsecode: 404, responsemessage: "Page not found"]
		};
		controller.getService = getServiceMock.createMock();

		controller.params.feedUrl1 = feedUrl;
		controller.params.feedColor1 = "ff0000";

		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feeds'", returnMap.feeds);
		assertEquals(1, returnMap.feeds.size());
		assertFeed(returnMap.feeds.get(0), feedUrl, feedUrl, "Unable to GET feed[404]: Page not found");
	}

	void testKml_feed_parse_exception() {

		def feedUrl = "http://localhost:8080/feed1";
		def feedParseException = "Unable to parse feed because you suck";

		//Set up mock for getService
		def getServiceMock = mockFor(GetService);
		getServiceMock.demand.getFeed(1..1) {String arg1, String arg2, String arg3 -> 
			return [responsecode: 200, content: "feed xml"]
		};
		controller.getService = getServiceMock.createMock();

		//Set up mock for feedParserService
		def feedParserServiceMock = mockFor(FeedParserService);
		feedParserServiceMock.demand.parseFeed(1..1) {String arg1, List<Filter> arg2 -> 
			throw new Exception(feedParseException);
		};
		controller.feedParserService = feedParserServiceMock.createMock();

		controller.params.feedUrl1 = feedUrl;
		controller.params.feedColor1 = "ff0000";

		Map returnMap = controller.kml();

		assertNotNull("Controller did not return map", returnMap);
		assertNotNull("Controller map does not contain expected model object: 'feeds'", returnMap.feeds);
		assertEquals(1, returnMap.feeds.size());
		assertFeed(returnMap.feeds.get(0), feedUrl, feedUrl, "Parse Exception: " + feedParseException);
	}

	private void assertFeed(Feed feed, String expectedUrl, String expectedTitle, String expectedDescription) {
		assertEquals("feed.url does not contain expected value",
			expectedUrl, feed.url);
		assertEquals("feed.title does not contain expected value",
			expectedTitle, feed.title);
		assertEquals("feed.description does not contain expected value",
			expectedDescription, feed.description);
	}
}
